#ifndef _TCPSERVER_
#define _TCPSERVER_

/*

*/

#include "EventLoop.h"
#include "Acceptor.h"
#include "InetAddress.h"
#include "noncopyable.h"
#include "EventLoopThreadPool.h"
#include "Callback.h"

#include <functional>
#include <string>
#include <memory>
#include <atomic>
#include <unordered_map>

class TcpServer : noncopyable{
public:
    using ThreadInitCallback = std::function<void(EventLoop*)>;

    enum Option{
        kReusePort,
        kNoReusePort
    };

    TcpServer(EventLoop* loop, const InetAddress &listenAddr, 
        const std::string &nameArg,
        Option option = kNoReusePort);
    ~TcpServer();

    inline void setThreadInitCallback(const ThreadInitCallback& cb)  { threadInitCallback_ = cb; }
    inline void setConnectionCallback(const ConnectionCallback& cb) { connectionCallback_ = cb; }
    inline void setMessageCallback(const MessageCallback& cb) { messageCallback_ = cb; }
    inline void setWriteCallback(const WriteCallback& cb) { writeCallback_ = cb; }

    //这里设置线程个数，也就是设置了subloop的个数
    void setThreadNum(int threadNums);
    //开启服务器监听(subLoop)
    inline void start();                      
private:
    void newConnection(int sockfd, const InetAddress peerAddr);
    void removeConnection(const TcpConnectionPtr& conn);
    void removeConnectionInLoop(const TcpConnectionPtr& conn);  //??为什么不是EventLoop作为参数

    using ConnectionMap = std::unordered_map<std::string, TcpConnectionPtr>;

    EventLoop *loop_;                       //baseLoop,也就是MainLoop，运行acceptor（新用户连接）
    const std::string ipPort_;
    const std::string name_;
    std::unique_ptr<Acceptor> acceptor_;    //MainLoop中运行的acceptor（监听新连接事件）
    std::shared_ptr<EventLoopThreadPool> threadPool_; //one loop per thread，不一定只有一个loop，有可能是多个（setThreadNum设置）

    ConnectionCallback connectionCallback_; //新连接时候的回调
    MessageCallback  messageCallback_;      //有读写消息时的回调
    WriteCallback writeCallback_;           //消息发送完成之后的回调
    ThreadInitCallback threadInitCallback_; //loop线程初始化的回调
    
    std::atomic_int started_;
    int nextConnId_;
    ConnectionMap connections_;           //保存所有的连接
};

#endif